﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Zhaoxi.HeatExchange.Models;
using Modbus.Device;

namespace Zhaoxi.HeatExchange.ViewModels
{
    public class MainViewModel : IDisposable
    {
        public MainModel MainData { get; set; } = new MainModel();

        private readonly CancellationTokenSource _cts = new CancellationTokenSource();
        private readonly List<Task> _tasks = new List<Task>();
        private SerialPort _serialPort;
        private IModbusMaster _modbusMaster;
        private bool _isDisposed = false;

        // 防止从Modbus读取时触发写回
        private bool _suppressWriteFromRead = false;

        // Modbus配置参数（与ModBus Slave保持一致）
        private const string ComPort = "COM3"; // 对应VSPD创建的另一个串口
        private const int BaudRate = 9600;
        private const int DataBits = 8;
        private static readonly StopBits StopBits = StopBits.One;
        private static readonly Parity Parity = Parity.None;

        // 两个ModBus从站地址
        private const byte CoilSlaveAddress = 1; // 线圈从站地址（泵1状态）
        private const byte RegisterSlaveAddress = 2; // 寄存器从站地址（瞬时流量和热量）

        public MainViewModel()
        {
            InitializeModbusConnection();

            // 监听UI对泵状态的修改，并写入线圈
            MainData.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(MainData.Pump1State))
                {
                    if (_suppressWriteFromRead) return; // 避免读回触发写
                    try
                    {
                        _modbusMaster?.WriteSingleCoil(CoilSlaveAddress, 0, MainData.Pump1State);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"写入线圈失败：{ex.Message}");
                    }
                }
            };
        }

        /// <summary>
        /// 初始化Modbus RTU连接
        /// </summary>
        private void InitializeModbusConnection()
        {
            try
            {
                //MessageBox.Show($"正在初始化ModBus连接，串口: {ComPort}");

                // 初始化串口
                _serialPort = new SerialPort(ComPort, BaudRate, Parity, DataBits, StopBits)
                {
                    ReadTimeout = 1000,
                    WriteTimeout = 1000
                };

                //MessageBox.Show("正在打开串口...");
                _serialPort.Open();
                //MessageBox.Show("串口打开成功！");

                // 创建Modbus主站
                _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort);
                _modbusMaster.Transport.ReadTimeout = 500;
                _modbusMaster.Transport.WriteTimeout = 500;
                //MessageBox.Show("ModBus主站创建成功！");

                // 启动数据读取任务
                StartDataReadingTask();
                //MessageBox.Show("数据读取任务已启动！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Modbus初始化失败：{ex.Message}\n详细错误：{ex}");
            }
        }

        /// <summary>
        /// 启动数据读取任务（支持两个ModBus从站）
        /// </summary>
        private void StartDataReadingTask()
        {
            _tasks.Add(Task.Run(async () =>
            {
                while (!_cts.IsCancellationRequested)
                {
                    try
                    {
                        if (!_serialPort.IsOpen)
                        {
                            //MessageBox.Show("串口已关闭，尝试重连...");
                            _serialPort.Open();
                            await Task.Delay(1000);
                            continue;
                        }

                        // 1. 从ID=1的从站读取线圈状态（泵1状态）
                        try
                        {
                            bool[] coils = _modbusMaster.ReadCoils(CoilSlaveAddress, 0, 1);
                            _suppressWriteFromRead = true;
                            MainData.Pump1State = coils[0];
                            _suppressWriteFromRead = false;
                            //MessageBox.Show($"从站{CoilSlaveAddress} - 泵1状态: {coils[0]}");
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show($"读取线圈数据失败：{ex.Message}");
                        }

                        // 如果泵未开启，则清零数据并跳过本轮寄存器读取
                        if (!MainData.Pump1State)
                        {
                            MainData.MomentDataList[0].Value = 0;
                            MainData.MomentDataList[1].Value = 0;
                            await Task.Delay(200, _cts.Token);
                            continue;
                        }

                        // 2. 从ID=2的从站读取保持寄存器（瞬时流量和热量）
                        try
                        {
                            ushort[] registers = _modbusMaster.ReadHoldingRegisters(
                                RegisterSlaveAddress,
                                0,  // 寄存器起始地址
                                2   // 读取2个寄存器
                            );

                            // 数据转换
                            MainData.MomentDataList[0].Value = registers[0] * 0.1;
                            MainData.MomentDataList[1].Value = registers[1] * 0.1;
                            MainData.HistoryValues[2].Value = registers[0];

                            //MessageBox.Show($"从站{RegisterSlaveAddress} - 瞬时流量: {registers[0]}, 瞬时热量: {registers[1]}");
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show($"读取寄存器数据失败：{ex.Message}");
                        }

                        // 延迟200ms
                        await Task.Delay(200, _cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        break; // 任务取消，正常退出
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"Modbus通信错误：{ex.Message}");
                        await Task.Delay(1000); // 出错后延迟重试
                    }
                }
            }, _cts.Token));
        }

        // 资源释放
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed) return;

            if (disposing)
            {
                // 取消任务
                _cts.Cancel();
                Task.WaitAll(_tasks.ToArray());
                _cts.Dispose();
            }

            // 关闭串口
            if (_serialPort?.IsOpen == true)
                _serialPort.Close();
            _serialPort?.Dispose();

            _isDisposed = true;
        }
    }
}
